package com.sdy.hospitalguard.h5.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.IdCardUtil;
import com.sdy.hospitalguard.biz.dto.*;
import com.sdy.hospitalguard.biz.model.*;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.hospitalguard.biz.utils.VisitDateUtil;
import com.sdy.hospitalguard.h5.vo.PatientRegisterVO;
import com.sdy.mvc.controller.BaseController;
import com.sdy.redis.service.RedisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: 王越洋
 * @version: v1.0
 * @description: com.sdy.hospitalguard.h5.controller
 * @date:2020/5/11
 */

@Slf4j
@RestController
@Api(tags = "患者注册接口")
public class PatientController extends BaseController {
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private BuildingService buildingService;
    @Autowired
    private SickbedService sickbedService;
    @Autowired
    private InpatientAreaService inpatientAreaService;
    @Autowired
    private RegulationsService regulationsService;
    @Autowired
    private MatchingPeopleService matchingPeopleService;
    @Autowired
    private RecordOfAccessService recordOfAccessService;
    @Autowired
    private AccessControlTerminalService accessControlTerminalService;
    @Autowired
    private RedisService redisService;

    public static void checkData(PatientRegisterVO hospitalUser) throws BizException {
        Assert.isTrue(StringUtils.isBlank(hospitalUser.getName()), "请规范填写姓名!");
        Assert.isTrue(!IdCardUtil.IDCardValidate(hospitalUser.getIdCard()).equals("true"), "身份证格式错误");
        Assert.isTrue(!hospitalUser.getPhone().matches(com.sdy.common.constant.Constants.REGEX_PHONE), "手机号格式错误");
    }

    @PostMapping("/patientRegister")
    @ApiOperation(value = "患者注册", response = PatientRegisterVO.class)
    public Response patientRegister(@RequestBody PatientRegisterVO pa, HttpServletRequest request) throws Exception {
        //住院号效验 待完成
        //床号效验  待完成
        Integer userId = getUserId(request);
        Assert.isNull(userId, "此用户不存在!");
        Assert.isNull(pa.getName(), "姓名不能为空!");
        Assert.isNull(pa.getIdCard(), "身份证号不能为空!");
        Assert.isNull(pa.getPhone(), "手机号不能为空!");
        List<PatientInformation> list1 = patientInformationService.lambdaQuery()
                .eq(PatientInformation::getAdmissionNumber, pa.getAdmissionNumber())
                .eq(PatientInformation::getPatientState, 0)
                .list();
        Assert.isTrue(list1.size() > 0, "住院号已存在!");
        HospitalUser byId = hospitalUserService.getById(userId);
        checkData(pa);
        if (byId.getIdCard() == null || "".equals(byId.getIdCard())) {
            hospitalUserService.userRegister(new HospitalUser()
                    .setIdCard(pa.getIdCard()).setName(pa.getName()).setPhone(pa.getPhone()), userId);
        }
        List<PatientInformation> list = patientInformationService.lambdaQuery()
                .eq(PatientInformation::getUserId, userId)
                .eq(PatientInformation::getPatientState, 0)
                .list();
        if (list.size() > 0) {
            return Response.error("已有患者信息,请勿重复添加");
        }
        Boolean aBoolean = patientInformationService.patientRegister(new PatientInformation()
                .setSickbedId(pa.getSickbedId())
                .setAdmissionNumber(pa.getAdmissionNumber())
                .setFloorId(pa.getFloorId()), userId);
        Assert.notTrue(aBoolean, "注册失败!");
        boolean update = sickbedService.lambdaUpdate().eq(Sickbed::getId, pa.getSickbedId())
                .set(Sickbed::getState, 1)
                .update();
        Assert.notTrue(update, "床位添加失败!");
        return Response.success(aBoolean);
    }

    @GetMapping("/patientQuery")
    @ApiOperation(value = "患者查询", response = PatientDetailsDTO.class)
    public Response patientQuery(HttpServletRequest request) throws BizException {
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前登录用户为空");
        // 当前陪护规则
        Integer escortAssociatedCounts = Integer.valueOf(regulationsService.selectEscortAssociatedRule(userId));
        PatientDetailsDTO patientDetailsDTO = patientInformationService.patientQuery(userId);
        HospitalUser byId = hospitalUserService.getById(userId);
        if (patientDetailsDTO != null) {
            patientDetailsDTO.setEscortAssociatedCounts(escortAssociatedCounts).setHeadPortrait(byId.getPhotoPath());
        } else {
            Assert.isNull(patientDetailsDTO, "用户没有患者信息!");
        }
        return Response.success(patientDetailsDTO);
    }

    @GetMapping("/patientTodayVisit")
    @ApiOperation(value = "患者今日探视查询", response = VisitAppointmentDTO.class)
    @ApiImplicitParam(value = "患者ID", name = "patientId")
    public Response patientTodayVisit(Integer patientId) throws BizException {
        List<VisitAppointmentDTO> visitAppointmentDTO = visitAppointmentService.patientTodayVisit(patientId);
        if (visitAppointmentDTO.size() > 0) {
            for (VisitAppointmentDTO v : visitAppointmentDTO) {
                v.setVisitTime(VisitDateUtil.visitTime(v.getVisitStartTime(), v.getVisitEndTime()));
            }
        }
        return Response.success(visitAppointmentDTO);
    }

    @GetMapping("/patientAllVisit")
    @ApiOperation(value = "患者所有探视分类查询", response = VisitAppointmentDTO.class)
    @ApiImplicitParam(value = "患者ID", name = "patientId")
    public Response patientAllVisit(Integer patientId, Page page) throws BizException {
        IPage<VisitAppointmentDTO> visitAppointments = visitAppointmentService.patientAllVisit(page, patientId);
        if (visitAppointments.getRecords().size() > 0) {
            List<VisitAppointmentDTO> records = visitAppointments.getRecords();
            for (VisitAppointmentDTO v : records) {
                v.setVisitTime(VisitDateUtil.visitTime(v.getVisitStartTime(), v.getVisitEndTime()));
            }
        }
        return Response.success(visitAppointments);
    }

    @PostMapping("/patientAddRelation")
    @ApiOperation(value = "患者添加陪护", response = HospitalUser.class)
    public Response patientAddRelation(@RequestBody HospitalUser hospitalUser, HttpServletRequest request) throws BizException, InterruptedException {
        Assert.isTrue(StringUtils.isBlank(hospitalUser.getName()), "请规范填写姓名!");
        Assert.isTrue(!IdCardUtil.IDCardValidate(hospitalUser.getIdCard()).equals("true"), "身份证格式错误");
        Assert.isTrue(!hospitalUser.getPhone().matches(com.sdy.common.constant.Constants.REGEX_PHONE), "手机号格式错误");
        Boolean aBoolean = patientInformationService.patientAddRelation(hospitalUser, request);
        return Response.success(aBoolean);
    }

    @GetMapping("/patientRelationQuery")
    @ApiOperation(value = "患者查询家属", response = EscortAssociatedDTO.class)
    @ApiImplicitParam(value = "患者ID", name = "patientId")
    public Response patientRelationQuery(Integer patientId) {
        List<EscortAssociated> escortList = escortAssociatedService.lambdaQuery()
                .select(EscortAssociated::getId, EscortAssociated::getUserId, EscortAssociated::getAttendantState, EscortAssociated::getFlowState)
                .eq(EscortAssociated::getPatientId, patientId)
                .in(EscortAssociated::getAttendantState, 0, 2)
                .in(EscortAssociated::getFlowState, 0, 1)
                .list();
        List<EscortAssociatedDTO> dto = new ArrayList<>();
        for (EscortAssociated e : escortList) {
            HospitalUser byId = hospitalUserService.getById(e.getUserId());
            EscortAssociatedDTO escortAssociatedDTO = new EscortAssociatedDTO();
            escortAssociatedDTO.setId(e.getId());
            escortAssociatedDTO.setName(byId.getName());
            escortAssociatedDTO.setPatientId(e.getPatientId());
            escortAssociatedDTO.setAttendantState(e.getAttendantState());
            escortAssociatedDTO.setFlowState(e.getFlowState());
            dto.add(escortAssociatedDTO);
        }
        return Response.success(dto);
    }

    @PostMapping("/patientSwitchEscort")
    @ApiOperation("患者切换陪护家属")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "type", value = "0:取消陪护,1:设为陪护"),
            @ApiImplicitParam(dataType = "Integer", name = "escortId", value = "id 陪护表ID"),
    })
    public Response switchEscort(HttpServletRequest request, Integer type, Integer escortId) throws BizException {
        //查询陪护信息
        EscortAssociated byId1 = escortAssociatedService.getById(escortId);
        //查询陪护者信息
        HospitalUser byId2 = hospitalUserService.getById(byId1.getUserId());
        Assert.isNull(byId1, "此陪护者不存在!");
        Assert.isNull(type, "类型不能为空!");
        if (type == 0) {
            //取消陪护
            PatientInformation patientInformation = patientInformationService.getById(byId1.getPatientId());
            MatchingPeopleDTO matchingPeopleDTO = new MatchingPeopleDTO();
            matchingPeopleDTO.setUserId(byId1.getUserId());
            matchingPeopleDTO.setPatientId(byId1.getPatientId());
            matchingPeopleDTO.setBuilding(patientInformation.getFloorId());
            boolean success = matchingPeopleService.delete(matchingPeopleDTO);
            Assert.notTrue(success, "解除闸机绑定失败!");
            boolean update = escortAssociatedService.lambdaUpdate()
                    .eq(EscortAssociated::getId, escortId)
                    .set(EscortAssociated::getFlowState, 1)
                    .update();
            return Response.success(update);
        } else if (type == 1) {
            //设为陪护
            //查询患者有几个正在陪护
            Integer count = escortAssociatedService.lambdaQuery()
                    .eq(EscortAssociated::getPatientId, byId1.getPatientId())
                    .eq(EscortAssociated::getAttendantState, 0)
                    .eq(EscortAssociated::getStatus, 0)
                    .eq(EscortAssociated::getFlowState, 0)
                    .count();
            //查询规则
            String escortAssociatedCounts = regulationsService.selectEscortAssociatedRule(byId1.getPatientId());
            if (count >= Integer.parseInt(escortAssociatedCounts)) {
                return Response.error("您当前已有陪护者,请取消当前陪护者再次尝试!");
            } else {
                //当前无陪护者
                //查询当前陪护信息
                EscortAssociated one = escortAssociatedService.lambdaQuery().eq(EscortAssociated::getId, escortId).one();
                //获取当前登录用户信息
                Integer userId = getUserId(request);
                HospitalUser byId = hospitalUserService.getById(userId);
                //判断是否经过审核
                if (one.getFlowState() == 1 & one.getAttendantState() == 2) {
                    //未审核 发送消息
                    //查询当前患者正在陪护是谁
                    EscortAssociated one2 = escortAssociatedService.lambdaQuery()
                            .eq(EscortAssociated::getPatientId, byId1.getPatientId())
                            .eq(EscortAssociated::getAttendantState, 0)
                            .eq(EscortAssociated::getStatus, 0)
                            .eq(EscortAssociated::getFlowState, 1)
                            .orderByDesc(EscortAssociated::getUpdateTime)
                            .last("LIMIT 0,1").one();
                    //查询当前患者信息
                    PatientInformation byId3 = patientInformationService.getById(byId1.getPatientId());

                    List<AccessControlTerminal> list = accessControlTerminalService.lambdaQuery()
                            .eq(AccessControlTerminal::getBuilding, byId3.getFloorId())
                            .list();
                    List<Integer> list2 = new ArrayList<>();
                    for (AccessControlTerminal a : list) {
                        list2.add(a.getId());
                    }
//                    String join = String.join(",", list2);
                    RecordOfAccess one3 = recordOfAccessService.lambdaQuery()
                            .eq(RecordOfAccess::getUserId, one2.getUserId())
                            .in(RecordOfAccess::getAccessId, list2)
                            .orderByDesc(RecordOfAccess::getCollectedTime)
                            .last("LIMIT 0,1").one();
                    if (one3.getTurnoverState() == 0) {
                        return Response.error("您的上一个陪护人员还未出院!");
                    } else {
                        Notice one1 = noticeService.lambdaQuery()
                                .eq(Notice::getAssociationId, escortId)
                                .eq(Notice::getHandlerId, byId1.getUserId())
                                .eq(Notice::getResult, 0)
                                .eq(Notice::getType, 1)
                                .one();
                        if (one1 != null) {
                            boolean b = noticeService.removeById(one1.getId());
                            Assert.notTrue(b, "删除消息失败!");
                        }
                        Notice notice = new Notice()
                                .setAssociationId(escortId)
                                .setSendUserId(userId)
                                .setHandlerId(byId1.getUserId())
                                .setType(1)
                                .setState(1)
                                .setResult(0)
                                .setMessageContent(byId.getName() + "向你发起陪护关联")
                                .setCreateTime(new Date());
                        boolean save1 = noticeService.save(notice);
                        Assert.notTrue(save1, "消息发送失败");
                    }
                } else if (one.getFlowState() == 1 & one.getAttendantState() == 0) {
                    //已审核
                    boolean c = escortAssociatedService.lambdaQuery()
                            .eq(EscortAssociated::getUserId, byId1.getUserId())
                            .eq(EscortAssociated::getAttendantState, 0)
                            .eq(EscortAssociated::getFlowState, 0)
                            .count() > 0;
                    if (c) {
                        Assert.isTrue(c, "此陪护者正在陪护其他患者!");
                    } else {
                        EscortAssociated one2 = escortAssociatedService.lambdaQuery()
                                .eq(EscortAssociated::getPatientId, byId1.getPatientId())
                                .eq(EscortAssociated::getAttendantState, 0)
                                .eq(EscortAssociated::getFlowState, 1)
                                .orderByDesc(EscortAssociated::getUpdateTime)
                                .last("LIMIT 0,1").one();
                        PatientInformation byId3 = patientInformationService.getById(byId1.getPatientId());
                        List<AccessControlTerminal> list = accessControlTerminalService.lambdaQuery()
                                .eq(AccessControlTerminal::getBuilding, byId3.getFloorId())
                                .list();
                        List<Integer> list2 = new ArrayList<>();
                        for (AccessControlTerminal a : list) {
                            list2.add(a.getId());
                        }
//                        String join = String.join(",", list2);
                        //查询出入记录
                        RecordOfAccess one3 = recordOfAccessService.lambdaQuery()
                                .eq(RecordOfAccess::getUserId, one2.getUserId())
                                .in(RecordOfAccess::getAccessId, list2)
                                .orderByDesc(RecordOfAccess::getCollectedTime)
                                .last("LIMIT 0,1").one();
                        if (one3 == null) {
                            boolean update = escortAssociatedService.lambdaUpdate()
                                    .eq(EscortAssociated::getId, escortId)
                                    .set(EscortAssociated::getFlowState, 0)
                                    .update();
                            //添加闸机身份
                            MatchingPeople matchingPeople = new MatchingPeople();
                            matchingPeople.setUserId(byId1.getUserId());
                            matchingPeople.setName(byId2.getName());
                            matchingPeople.setCardId(byId2.getIdCard());
                            matchingPeople.setRemark("陪护人员");
                            matchingPeople.setFaceId(byId1.getUserId());
                            matchingPeople.setPhotoPath(byId2.getPhotoPath());
                            matchingPeople.setBuilding(patientInformationService.getById(byId1.getPatientId()).getFloorId());
                            matchingPeople.setLastChange(String.valueOf(System.currentTimeMillis() / 1000));
                            matchingPeople.setStatus(0);
                            boolean success2 = matchingPeopleService.add(matchingPeople);
                            Assert.notTrue(success2, "添加闸机绑定失败!");
                            return Response.success(update);
                        } else {
                            if (one3.getTurnoverState() == 0) {
                                return Response.error("您的上一个陪护人员还未离开医院!");
                            } else {
                                boolean update = escortAssociatedService.lambdaUpdate()
                                        .eq(EscortAssociated::getId, escortId)
                                        .set(EscortAssociated::getFlowState, 0)
                                        .update();
                                //添加闸机身份
                                MatchingPeople matchingPeople = new MatchingPeople();
                                matchingPeople.setUserId(byId1.getUserId());
                                matchingPeople.setName(byId2.getName());
                                matchingPeople.setCardId(byId2.getIdCard());
                                matchingPeople.setRemark("陪护人员");
                                matchingPeople.setFaceId(byId1.getUserId());
                                matchingPeople.setPhotoPath(byId2.getPhotoPath());
                                matchingPeople.setBuilding(patientInformationService.getById(byId1.getPatientId()).getFloorId());
                                matchingPeople.setLastChange(String.valueOf(System.currentTimeMillis() / 1000));
                                matchingPeople.setStatus(0);
                                boolean success2 = matchingPeopleService.add(matchingPeople);
                                Assert.notTrue(success2, "添加闸机绑定失败!");
                                return Response.success(update);
                            }
                        }
                    }
                } else {
                    return Response.error("陪护者状态异常!");
                }
            }
        } else {
            return Response.error("陪护者状态参数异常!");
        }
        return null;
    }

//    @PostMapping("/patientCancelRelation")
//    @ApiOperation("患者取消陪护家属")
//    @ApiImplicitParam(value = "陪护者ID", name = "escortId")
//    public Response patientCancelRelation(Integer escortId) throws BizException {
//        boolean update = escortAssociatedService.lambdaUpdate()
//                .eq(EscortAssociated::getId, escortId)
//                .set(EscortAssociated::getFlowState, 3)
//                .update();
//        // boolean b = escortAssociatedService.removeById(escortId);
//        Assert.notTrue(update, "解除陪护人员失败!");
//        return Response.success(update);
//    }

    @GetMapping("/getTree")
    @ApiOperation(value = "获取医院病区病房Tree", response = BuildingDTO.class)
    public Response getTree() {
        List<BuildingDTO> buildings = buildingService.queryBuilding(null);
        List<SickbedDTO> sickbeds = sickbedService.querySickbed(null);
        List<InpatientAreaDTO> inpatientAreas = inpatientAreaService.queryInpatientArea(null);
        boolean a = true;
        for (BuildingDTO b : buildings) {
            for (InpatientAreaDTO i : inpatientAreas) {
                if (b.getChildren() == null) {
                    b.setChildren(new ArrayList<InpatientAreaDTO>());
                }
                if (b.getId().equals(i.getBuildingId())) {
                    b.getChildren().add(i);
                }
                if (a) {
                    for (SickbedDTO s : sickbeds) {
                        if (i.getChildren() == null) {
                            i.setChildren(new ArrayList<SickbedDTO>());
                        }
                        if (i.getId().equals(s.getAreaId())) {
                            i.getChildren().add(s);
                        }
                    }
                }
            }
            a = false;
        }
        return Response.success(buildings);
    }
}
